#include "memory_impl.h"
#include "memory/memory.h"
#include "memory/Alloc.h"
#include "win.h"
#include <iostream>
#include "memory/MemoryTracker.h"

namespace KCore
{

Alloc g_alloc_memory_large(1024*1024*3);
Alloc g_alloc_memory_fix(1024*1024);

void* memory_large::alloc(size_t size)
{
	++num;
	space += size;
	memory_map::iterator it = m_frees.lower_bound(size);
	if (it == m_frees.end())
	{
		return g_alloc_memory_large.alloc_new(size,__FUNCTION__);
	}
	void* p = it->second;
	m_frees.erase(it);
	return p;
}

void memory_large::free(void* p,size_t size) 
{
	--num;
	space -= size;
	m_frees.insert(std::make_pair(size,p));
}


memory_large::~memory_large()
{
	for (memory_map::iterator it = m_frees.begin(); it != m_frees.end(); ++it)
	{
		g_alloc_memory_large.alloc_delete((char*)(it->second),it->first);
	}
	m_frees.clear();
//	report_leak();
}

memory_fix::memory_fix(size_t size) : m_pool(size)
{
	m_size = size;
	usernum = 0;
#ifdef __LINUX
	//sprintf(m_name.get_buffer(),"memory_fix_%d",size);
	std::stringstream ss;
	ss<<"memory_fix_"<<size<<"d"<<std::endl;
	m_name = ss.str();
#else
	std::stringstream ss;
	ss<<m_name.capacity()<<"memory_fix_"<<size<<"d"<<std::endl;
	m_name = ss.str();
	//sprintf(m_name.c_str(),m_name.capacity(),"memory_fix_%d",size);
#endif
}

memory_fix::~memory_fix()
{
//	report_leak();
}

void* memory_fix::alloc(size_t size)
{
	++usernum;
	g_alloc_memory_fix.add_size(size,__FUNCTION__);
	return m_pool.malloc();
}

void memory_fix::free(void* p,size_t size) 
{
	--usernum;
	g_alloc_memory_fix.dec_size(size);
	m_pool.free(p);
}

int memory_dynamic::forall_sum_cost(MEMFUNC_const f) const
{
	int sum = 0;
	for (std::vector<memory*> :: const_iterator it = m_aPool.begin(); it != m_aPool.end(); ++it)
		sum += ((*it)->*f)();
	return sum;
}

int memory_dynamic::forall_sum(MEMFUNC f)
{
	int sum = 0;
	for (std::vector<memory*> :: iterator it = m_aPool.begin(); it != m_aPool.end(); ++it)
		sum += ((*it)->*f)();
	return sum;
}

memory_dynamic::memory_dynamic()
{
	m_aPool.push_back(memory_init(MemoryLarge));
	for (int i=1; i<sizeof(c_memorysize)/sizeof(int);i++)
		m_aPool.push_back(memory_init(MemoryFix,c_memorysize[i]));
}

memory_dynamic::~memory_dynamic()
{
//	report_leak(std::cout);
	for (int i=0; i<sizeof(c_memorysize)/sizeof(int);i++)
		memory_clear(m_aPool[i]);
	m_aPool.clear();
}

int memory::report(std::stringstream& os) const
{
	os << "sys_num " << sys_num() 
		<< " sys_space " << sys_space()
		<< " user_num " << user_num()
		<< " user_space " << user_space() << std::endl;
	return 0;
}

void* memory_dynamic::debug_alloc(size_t size,const char *file,int line)
{
	void* p = alloc(size+sizeof(size_t));
	if (p)
	{
		size_t* _p = (size_t*)(p);
		//*_p = m_fl.add_debug(file,line);
#if _MEMORY_TRACKER
		MemoryTracker::get()._recordAlloc(p, size, 0, file, line, 0);
#endif
		return ++_p;
	}
	return 0;
}

void memory_dynamic::debug_free(void* p,size_t )
{
	size_t* _p = (size_t*)p-1;
#if _MEMORY_TRACKER
	MemoryTracker::get()._recordDealloc((void*)_p);
#endif
	*_p--;//m_fl.remove_debug(*_p--);
	size_t size = *_p;
	memory* pool = find_pool(size);
	if (pool)
		pool->free(_p,size);
}

int memory::report_leak(std::stringstream& os) const
{
	if (user_num())
	{
		os << __FUNCTION__ << " " << get_name() << " detect memory leak " << std::endl;
		//report(std::cout);
		return 1;
	}
	return 0;
}

int memory_dynamic::report_leak(std::stringstream& os) const
{
	int sum = 0;
	for (std::vector<memory*> :: const_iterator it = m_aPool.begin(); it != m_aPool.end(); ++it)
		sum += ((*it)->report_leak)(os);
	if (sum > 0)
	{
		os << __FUNCTION__ << " sum = " << sum << std::endl;
		//m_fl.report_fileline(os);
	}
	return sum;
}

};
